﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.IO;
using System.ComponentModel;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;

namespace Pavilion
{
    public class Frame
    {
        public NotifiableCollection<CTexture2D> TextureList { get; private set; }
        private Rectangle boundingBox;
        public Rectangle BoundingBox { get { return boundingBox; } }
        public bool EnableLoading { get; set; }
        public float OriginX { get; set; }
        public float OriginY { get; set; }

        public event Action<Frame> SizeChanged;

        public Frame()
        {
            TextureList = new NotifiableCollection<CTexture2D>();

            TextureList.Added += (CTexture2D texture, int index) =>
            {
                texture.TextureItemChanged += new Action<Texture>(Texture_TextureItemChanged);
                DetermineMaximumDimensions();
            };

            TextureList.Removed += (CTexture2D texture, int index) =>
            {
                texture.TextureItemChanged += new Action<Texture>(Texture_TextureItemChanged);
                DetermineMaximumDimensions();
            };

            boundingBox = new Rectangle();

            EnableLoading = true;
        }

        public Frame(CTexture2D[] textureCollection) : this()
        {
            TextureList.AddRange(textureCollection);
        }

        private void DetermineMaximumDimensions()
        {
            int width = 0;
            int height = 0;

            foreach (CTexture2D texture in TextureList)
            {
                if (width < texture.Width)
                    width = texture.Width;

                if (height < texture.Height)
                    height = texture.Height;
            }

            this.Width = width;
            this.Height = height;
        }

        public bool Load(string framePath)
        {
            if (!EnableLoading)
                return false;

            Unload();

            for (int i = 0; i < TextureList.Count; i++)
                TextureList[i].Load(framePath, i.ToString());

            return true;
        }

        public void CreateTexturesFromFolder(string framePath)
        {
            FileInfo[] fileList = new DirectoryInfo(framePath).GetFiles("*.xnb");

            foreach (FileInfo fileInfo in fileList)
            {
                CTexture2D texture = new CTexture2D();
                texture.Load(framePath, fileInfo.Name.Replace(".xnb", ""));
                TextureList.Add(texture);
            }
        }

        public bool Unload()
        {
            if (!EnableLoading)
                return false;

            foreach (CTexture2D texture in TextureList)
                texture.Unload();

            return true;
        }

        public void Draw(Vector2 position)
        {
            this.Draw(position, Color.White, 1f, SpriteEffects.None);
        }

        public void Draw(Vector2 position, Color color, float scale, SpriteEffects effects)
        {
            Vector2 workingOrigin = DetermineOrigin(effects);

            boundingBox.X = (int)(position.X - (workingOrigin.X * scale));
            boundingBox.Y = (int)(position.Y - (workingOrigin.Y * scale)) - 1;
            //boundingBox.Width = (int)(Width * scale) + 1;
            //boundingBox.Height = (int)(Height * scale) + 1;

            for (int i = 0; i < TextureList.Count; i++)
                TextureList[i].Draw(position, new Rectangle(0, 0, Width, Height), color, 0f, workingOrigin, scale, effects, 0f);
        }

        public void DrawOnScreen(Vector2 position, Color color, float scale, SpriteEffects effects)
        {
            Vector2 workingOrigin = DetermineOrigin(effects);

            boundingBox.X = (int)(position.X - (workingOrigin.X * scale));
            boundingBox.Y = (int)(position.Y - (workingOrigin.Y * scale)) - 1;
            //boundingBox.Width = (int)(Width * scale) + 1;
            //boundingBox.Height = (int)(Height * scale) + 1;

            for (int i = 0; i < TextureList.Count; i++)
                TextureList[i].DrawOnScreen(position, new Rectangle(0, 0, Width, Height), color, 0f, workingOrigin, scale, effects, 0f);
        }

        public void DrawBoundingBoxOnScreen(Color outlineColor, float scale)
        {
            DrawManager.Instance.DrawRectangleOnScreen(
                new Rectangle(boundingBox.X, boundingBox.Y,(int)(boundingBox.Width * scale), (int)(boundingBox.Height * scale)), outlineColor);
        }

        public Vector2 DetermineOrigin(SpriteEffects effects)
        {
            if (effects == SpriteEffects.FlipHorizontally)
                return new Vector2(Width - OriginX, OriginY);
            else
                return new Vector2(OriginX, OriginY);
        }

        /// <summary>
        /// Gets the width of this frame.
        /// </summary>
        public int Width
        {
            get { return boundingBox.Width; }
            private set
            {
                if (boundingBox.Width == value)
                    return;

                boundingBox.Width = value;

                OnSizeChanged();
            }
        }

        /// <summary>
        /// Gets the height of this frame.
        /// </summary>
        public int Height
        {
            get { return boundingBox.Height; }
            private set
            {
                if (boundingBox.Height == value)
                    return;

                boundingBox.Height = value;

                OnSizeChanged();
            }
        }

        private void OnSizeChanged()
        {
            if (SizeChanged != null)
                SizeChanged(this);
        }

        private void Texture_TextureItemChanged(Texture texture)
        {
            DetermineMaximumDimensions();
        }
    }
}
